#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>  /* See NOTES */
#include <netinet/ip.h> /* superset of previous */
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <pthread.h>
#include <modbus.h>
#include <errno.h>
#include "cJSON.h"
#include "shmem.h"
#include "msg_queue_peer.h"

#define MAX_NODE 128 // 最大支持设备数目

union data
{
    int a;
    float val;
};
struct stm32_data_msg
{
    long a;
    int key;  // 设备号
    int type; // 用switch case判断接收的数据类型s  1是bool,2是int,3是float
    union data val;
};

struct stm32_data_msg stm32data;

void *hander(void *acceptfd1)
{

    printf("进到现成了\n");
    // 客户端信息
    int acceptfd = *((int *)acceptfd1);
    char buf[128] = {0};
    stm32data.a = 1; // type1代表单片机

    // int LED1 = 0; // 灯1
    int LED3 = 0; // 灯2
    int FAN = 0;  // 风扇
    int LED4 = 0; // 灯3
                  //  sleep(20);

    int TEM = 0;
    int HUM = 0;

    float t;
    float h;
    while (1)
    {

        msg_queue_recv("queue", &stm32data, sizeof(stm32data), stm32data.a, 0);
        //////////////////////////////////标志位
        printf("key%d\n", stm32data.key);
        if (stm32data.key == 101)
        {
            TEM = 1; // 灯3
        }

        if (stm32data.key == 104)
        {
            LED3 = 1; // 灯3
            printf("------------%d\n", stm32data.key);
        }
        if (stm32data.key == 105)
        {
            // printf("风扇标志位开\n");
            FAN = 1; // 风扇
        }
        if (stm32data.key == 106)
        {
            LED4 = 1; // 灯4
        }

        if (stm32data.key == 107)
        {
            HUM = 1; // 灯3
        }
        //////////////////////////////////////通过标志位发送信息
        if (TEM == 1)
        {
            t = stm32data.val.val;
            if (t > 25)
            {
                sprintf(buf, "%s%.2f", "TEA", t);
                send(acceptfd, buf, sizeof(buf), 0);
            }
            else
            {
                sprintf(buf, "%s%.2f", "TEI", t);
                send(acceptfd, buf, sizeof(buf), 0);
            }
            TEM = 0;
        }

        if (FAN == 1)
        {
            // printf("风扇标志位进\n");
            if (stm32data.val.a == 1)
            {
                sprintf(buf, "%s", "FAN1");
                send(acceptfd, buf, sizeof(buf), 0);
            }
            else
            {
                // printf("风扇开关状态治为0\n");
                sprintf(buf, "%s", "FAN0");
                send(acceptfd, buf, 4, 0);
            }
            FAN = 0;
        }
        if (LED3 == 1)
        {
            // printf("风扇标志位进\n");
            if (stm32data.val.a == 1)
            {
                sprintf(buf, "%s", "LED31");
                send(acceptfd, buf, sizeof(buf), 0);
            }
            else if (stm32data.val.a == 0)
            {
                printf("++++++++++++%d\n", stm32data.key);
                // printf("风扇开关状态治为0\n");
                sprintf(buf, "%s", "LED30");
                send(acceptfd, buf, 5, 0);
            }
            LED3 = 0;
        }
        if (LED4 == 1)
        {
            // printf("风扇标志位进\n");
            if (stm32data.val.a == 1)
            {
                sprintf(buf, "%s", "LED41");
                send(acceptfd, buf, 5, 0);
                printf("急停关\n");
            }
            else
            {
                // printf("风扇开关状态治为0\n");
                sprintf(buf, "%s", "LED40");
                send(acceptfd, buf, 5, 0);
                printf("急停开\n");
            }
            LED4 = 0;
        }

        if (HUM == 1)
        {

            h = stm32data.val.val;
            if (h > 30)
            {
                sprintf(buf, "%s%.2f", "THA", h);
                send(acceptfd, buf, sizeof(buf), 0);
            }
            else
            {
                sprintf(buf, "%s%.2f", "THI", h);
                send(acceptfd, buf, sizeof(buf), 0);
            }

            TEM = 0;
        }

        memset(buf, 0, sizeof(buf));
    }

    sleep(1);
    return NULL; // 结束线程
}

int main(int argc, char *argv[])
{
    printf("进入32\n");
    //////////////////////////////////////////////////////
    /*        可以先向共享内存里面放入数据进行测试使用              */
    //  const char *json_data = "{"
    //                         "\"version\":\"v1.0\","
    //                         "\"report\":{\"type\":0,\"period\":5},"
    //                         "\"stm32\":{\"data\":["
    //                         "{\"key\":101,\"name\":\"Temp\",\"type\":3,\"value\":20.3,\"newval\":0},"
    //                         "{\"key\":102,\"name\":\"Door\",\"type\":1,\"value\":1,\"newval\":0},"
    //                         "{\"key\":103,\"name\":\"Led1\",\"type\":1,\"value\":0,\"newval\":0},"
    //                         "{\"key\":104,\"name\":\"Led2\",\"type\":1,\"value\":0,\"newval\":0},"
    //                         "{\"key\":105,\"name\":\"Fan\",\"type\":1,\"value\":0,\"newval\":0},"
    //                         "{\"key\":106,\"name\":\"Ekey\",\"type\":1,\"value\":0,\"newval\":0},"
    //                         "{\"key\":107,\"name\":\"Hum\",\"type\":3,\"value\":20.3,\"newval\":0}]},"
    //                         "\"modbus\":{\"data\":["
    //                         "{\"key\":201,\"name\":\"Etemp\",\"addr\":30001,\"type\":3,\"value\":20.3,\"newval\":0},"
    //                         "{\"key\":202,\"name\":\"Carbon\",\"addr\":30001,\"type\":3,\"value\":0.04,\"newval\":1},"
    //                         "{\"key\":203,\"name\":\"Revolution\",\"addr\":40001,\"type\":2,\"value\":0,\"newval\":0},"
    //                         "{\"key\":204,\"name\":\"Mdoor\",\"addr\":40000,\"type\":1,\"value\":1,\"newval\":0}]"
    //                         "}}";

    // strcpy(shm_p, json_data);//放到共享内存中
    ///////////////////////////////////////////////////////////
    int ret = 0;
    int acceptfd;
    char buff[1024];
    // long stm23type=1;

    // 1.创建流式套接字（socket）---------》有手机
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd);
    // 2.指定网络信息--------------------------》有号码
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = INADDR_ANY;
    int len = sizeof(caddr);

    int optval = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
    {
        perror("setsockopt");
        close(sockfd);
        return -1;
    }
    // 3.绑定套接字（bind）-----------------》绑定手机
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind errr");
        return -1;
    }
    printf("bind ok\n");
    // 4.监听套接字（listen）----------------》待机
    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok\n");
    acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
    pthread_t tid;
    pthread_create(&tid, NULL, hander, &acceptfd);
    // pthread_create(&tid,NULL,hander,NULL);
    pthread_detach(tid);

    printf("accetfd:%d\n", acceptfd); // 4
    printf("port:%d ip:%s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));

    key_t key; // 用于识别共享内存的键值
    int shmid; // 共享内存的标识符

    struct shm_param para;
    if (shm_init(&para, "mqtt_json", 4096) == -1)
    {
        perror("shm_init err\n");
        return -1;
    }

    // key = ftok("mqqt_json", 65); // shmfile是一个存在的文件名，65是一个项目ID

    // 映射共享内存
    char *shm_p = shm_getaddr(&para); // 共享内存地址
    while (1)
    {
        if (NULL != shm_p)
        {
            perror("开始写入数据\n");
            break;;
        }
    }
    char *dest = buff;
    int n1 = 0;
    int n2 = 5;
    int n3 = 6;
    int n4 = 11;
    int n5 = 12;
    int n6 = 16;
    int n7 = 15;
    int n8 = 20;
    int n9 = 25;
    int n10 = 30;

    char TEM[32];
    char HUM[32];
    char FAN[32];

    char LED1[32]; // 灯1的状态也是门的状态
    char LED3[32]; // 电机的启动停止
    char LED4[32]; // 电机的急停和重启

    int FA = 1;
    int L1 = 1;
    int L3 = 1;
    int L4 = 1;

    // 5.接收客户端连接请求（accept）--》接电话
    while (1)
    {

        recv(acceptfd, buff, sizeof(buff), 0);
        printf("%s\n", buff);
        strncpy(TEM, dest + n1, n2 - n1);
        strncpy(HUM, dest + n2, n4 - n3); // 五个字符用两个空间，最后留一个加\n
        strncpy(FAN, dest + n4 - 1, n6 - n5);
        strncpy(LED1, dest + n6 - 2, n8 - n7 - 1);
        // strncpy(HUM,dest+n7,n8-n7);
        strncpy(LED3, dest + 18, 22);
        strncpy(LED4, dest + 23, 27);
        TEM[n2 - n1] = '\0';
        HUM[n4 - n3] = '\0';
        FAN[n6 - n5] = '\0';
        LED1[n8 - n7 - 1] = '\0';
        LED3[5] = '\0';
        LED4[6] = '\0';
        float T = atof(TEM);
        float H = atof(HUM);

        // 风扇
        if (!strncmp(FAN, "fan1", 4))
        {
            FA = 1;
        }
        else if (!strncmp(FAN, "fan0", 4))
        {
            FA = 0;
        }
        // LED1
        if (!strncmp(LED1, "led1", 4))
        {
            L1 = 1;
        }
        else if (!strncmp(LED1, "led0", 4))
        {
            L1 = 0;
        }

        // LED3
        if (!strncmp(LED3, "LED31", 5))
        {
            L3 = 1;
        }
        else if (!strncmp(LED3, "LED30", 5))
        {
            L3 = 0;
        }

        // LED4
        if (!strncmp(LED4, "LED41", 5))
        {
            L4 = 1;
        }
        else if (!strncmp(LED4, "LED40", 5))
        {
            L4 = 0;
        }

        cJSON *root; // 树根
        root = cJSON_Parse(shm_p);
        if (!root)
        {
            const char *error_ptr = cJSON_GetErrorPtr();
            if (error_ptr != NULL)
            {
                fprintf(stderr, "ERROR before :%s\n", error_ptr);
            }
            return 1;
        }

        cJSON *stm32 = cJSON_GetObjectItem(root, "stm32"); // 根节点的32分节点
        cJSON *data = cJSON_GetObjectItem(stm32, "data");  // 32中的数据
        int n = cJSON_GetArraySize(data);
        for (int i = 0; i < n; i++)
        {
            cJSON *item = cJSON_GetArrayItem(data, i);
            cJSON *key = cJSON_GetObjectItem(item, "key");

            if (key->valueint == 101) // 温度
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");

                cJSON_SetNumberValue(newval, T);
                printf("TEM:%.2f\n", newval->valuedouble);
            }
            else if (key->valueint == 102) // door实则是灯1
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");

                // newval->valueint;
                cJSON_SetNumberValue(newval, L1);
                printf("LED1:%.d\n", newval->valueint);
            }
            else if (key->valueint == 103) // LED1实则是灯1
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");

                // newval->valueint;
                cJSON_SetNumberValue(newval, L1);
                printf("LED1 door:%d\n", newval->valueint);
            }
            else if (key->valueint == 104) // LED3电机的启动停止(LED2)
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");

                cJSON_SetNumberValue(newval, L3);
                printf("led3:%d\n", newval->valueint);
            }
            else if (key->valueint == 105) // 风扇
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");

                // newval->valueint;
                cJSON_SetNumberValue(newval, FA);
                printf("FAN:%d\n", newval->valueint);
            }
            else if (key->valueint == 106) // 电机急停
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");

                // newval->valueint;
                cJSON_SetNumberValue(newval, L4);
                printf("LED4:%d\n", newval->valueint);
            }
            else if (key->valueint == 107) // 湿度
            {
                cJSON *newval = cJSON_GetObjectItem(item, "newval");

                // newval->valuedouble;
                cJSON_SetNumberValue(newval, H);

                printf("HUM:%.2f\n", newval->valuedouble);
            }
        }
        char *updated_json_data = cJSON_Print(root);
        if (updated_json_data == NULL)
        {
            perror("cJSON_Print failed");
            cJSON_Delete(root);
            continue;
        }
        strcpy(shm_p, updated_json_data);
        // printf("%s\n", shm_p);
        free(updated_json_data);
        updated_json_data = NULL;
        cJSON_Delete(root);

        // 7.关闭套接字（close）----------------》挂电话
        memset(buff, 0, sizeof(buff));
        memset(TEM, 0, sizeof(TEM));
        memset(LED1, 0, sizeof(LED1));
        memset(LED3, 0, sizeof(LED3));
        memset(LED4, 0, sizeof(LED4));
        memset(FAN, 0, sizeof(FAN));
        memset(HUM, 0, sizeof(HUM));
        memset(TEM, 0, sizeof(TEM));
    }
    close(acceptfd);
    close(sockfd);

    return 0;
}